package drds.plus.executor.cursor.cursor.impl.result_cursor;

import drds.plus.executor.ExecuteContext;
import drds.plus.executor.cursor.cursor.ISortingCursor;
import drds.plus.executor.cursor.cursor.impl.SortingCursor;
import drds.plus.executor.row_values.RowValues;
import drds.tools.Threads;

import java.util.Iterator;
import java.util.List;


public class ResultCursor extends SortingCursor {

    public static final String AFFECT_ROW = "AFFECT_ROW";
    protected boolean closed = false;
    protected Long txn_id;
    protected Integer result_id;
    protected String exception;
    protected List<RowValues> results;
    protected Iterator<RowValues> iterator;
    protected int size = 10;
    protected int totalCount;
    protected List<Object> originalSelectColumns;
    private ExecuteContext executeContext;

    public ResultCursor(ExecuteContext executeContext) {
        super(null, null, null);
        this.executeContext = executeContext;
    }

    public ResultCursor(ISortingCursor cursor, ExecuteContext executeContext) throws RuntimeException {
        super(cursor, null, cursor == null ? null : cursor.getOrderByList());
        this.executeContext = executeContext;
    }

    public ResultCursor(ExecuteContext executeContext, ISortingCursor cursor, List<Object> originalSelectColumns) throws RuntimeException {
        super(cursor, null, cursor == null ? null : cursor.getOrderByList());
        this.executeContext = executeContext;
        this.originalSelectColumns = originalSelectColumns;
    }

    public List<Object> getOriginalSelectColumns() {
        return originalSelectColumns;
    }

    public void setOriginalSelectColumns(List<Object> originalSelectColumns) {
        this.originalSelectColumns = originalSelectColumns;
    }

    public ExecuteContext getExecuteContext() {
        return executeContext;
    }

    public void setExecuteContext(ExecuteContext executeContext) {
        this.executeContext = executeContext;
    }

    public String getException() {
        return exception;
    }

    public void setException(String exception) {
        this.exception = exception;

    }

    public Integer getResultID() {
        return result_id;
    }

    public void setResultId(Integer result_id) {
        this.result_id = result_id;

    }

    public void setSize(int n) {
        this.size = n;
    }

    public int getTotalCount() {
        return totalCount;
    }

    public Long getTxnID() {
        return txn_id;
    }

    protected void closeStatus() {
        closed = true;
    }

    protected void throwExceptionIfClosed() {
        if (closed) {
            throw new IllegalStateException("alread closed");
        }
    }

    public void setTransactionID(Long txn_id) {
        this.txn_id = txn_id;

    }

    public void setResultCount(Integer count) {
        this.totalCount = count;

    }

    public void setResults(List<RowValues> results) {
        this.results = results;
        if (results != null) {
            iterator = results.iterator();
        }

    }

    public Object getIngoreTableName(RowValues rowData, String column, String columnAlias) {
        if (rowData == null) {
            return null;
        }
        Integer index = getIndex(rowData, column, null, columnAlias);
        return rowData.getObject(index);
    }

    private Integer getIndex(RowValues rowData, String column, String tableName, String columnAlias) {
        Integer index = rowData.getParentCursorMetaData().getIndex(tableName, column, columnAlias);
        if (index == null) {
            throw new IllegalArgumentException("can't find indexMapping by " + tableName + "." + column + " .");
        }
        return index;
    }

    public Object get(RowValues rowData, String table, String column, String columnAlias) {
        if (rowData == null) {
            return null;
        }
        Integer index = getIndex(rowData, column, table, columnAlias);
        return rowData.getObject(index);
    }

    public RowValues next() throws RuntimeException {
        if (closed) {
            return null;
        }
        return parentCursorNext();
    }

    public String getException(Exception e, ResultCursor cursor) {
        if (e instanceof RuntimeException) {
            // 已知异常，是有状态码的，定义过处理逻辑。
            return e.getMessage();
        }
        String targetException = "";
        if (cursor != null) {
            targetException = cursor.getException();
        }
        return targetException;
    }

    public void beforeFirst() throws RuntimeException {
        throwExceptionIfClosed();
        Threads.checkInterrupted();
        if (result_id == null) {
            if (this.results == null)
                return;
            iterator = results.iterator();

        } else {
            if (results != null) {
                results.clear();
                iterator = results.iterator();
            }
            super.beforeFirst();
        }
    }

    public List<RuntimeException> close(List<RuntimeException> exceptions) {
        if (closed) {
            return exceptions;
        }
        closed = true;
        List<RuntimeException> ex = parentCursorClose(exceptions);
        executeContext.cleanTempTables();
        return ex;
    }

    public String toStringWithInden(int inden) {
        StringBuilder sb = new StringBuilder();
        sb.append("result : ").append("\n");
        sb.append(cursor.toStringWithInden(inden));
        return sb.toString();
    }

    public String toString() {
        return toStringWithInden(0);
    }

}
